#!/usr/bin/env python 
'''
Copyright (C) 2012 I&He, az@azijeon.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
'''
import inkex, simplestyle, pturtle, random, subprocess, os, sys, embedimage, tempfile, azijeon, re, time

import gettext
_ = gettext.gettext

from embedimage import Embedder

from subprocess         import call
from azijeon            import command, Svg_Link
from azijeon.Svg_Link   import SvgLinkProject

from SvgLinkProject import SvgLinkProject

from subprocess import Popen, PIPE

class Azijeon_SVG_Link(inkex.Effect):
    
    def __init__(self):
        inkex.Effect.__init__(self)
        
        self.embeder = Embedder()
                
        self.OptionParser.add_option("--cmd", "--command",
                        action="store", type="string", 
                        dest="command", default="",
                        help="Function to execute")
        
        self.OptionParser.add_option("--pt", "--link_path",
                        action="store", type="string", 
                        dest="link_path", default="",
                        help="Path to the imported file")
        
        
        self.OptionParser.add_option("--dp", "--doc_path",
                        action="store", type="string", 
                        dest="doc_path", default="",
                        help="Path to the source file")
        
       
        
    
    def create_link(self):        
    
        project = self.project.get_project_layer()
        
        if project is None:
            inkex.errormsg("You must first setup a project!")
        
        
        if not os.path.exists(self.project.get_project_path()):
            inkex.errormsg(_("Project path is invalid!"))
        
        
        import_path = self.options.link_path
        
        target_doc = inkex.etree.parse(import_path);
        
        width   = target_doc.getroot().get('width', '')         
        height  = target_doc.getroot().get('height', '')        
                
        data    = os.path.relpath(import_path, self.options.doc_path)
        
        
        import_path = self.make_rel_embed_path(import_path)
        
        
        
        attribs = {
                'class'                 : 'Azijeon_SVG_Link',
                'data-embed'            : import_path,
                'width'                 : width,
                'height'                : height,
                'data-test'             : data	
        }
        
        
        node = inkex.etree.SubElement(self.current_layer, inkex.addNS('image','svg'), attribs)  
        
        self.render_node(node)
        
    def render_node(self, node):
        
        target_svg = self.get_abs_embed_path(node.get('data-embed'))
        
        if not os.path.exists(target_svg):
            inkex.errormsg(_("File is Missing: " + target_svg) )
            return
        
        
        
        render_size = node.get('data-render-size', '0x0')
        render_size = render_size.split('x')
        
        
        # Calculate transform correction based on parent chain of scale transformations to determine the optimal rendering resolution
        transform = {'x' : 1, 'y': 1}
        
        n = node
        
        while(n is not None):
            
            result = self.get_transform(n)
            
            transform['x'] *= float(result['x'])
            transform['y'] *= float(result['y'])
            
            n = n.getparent()

        
        
        file_descriptor, temp_file = tempfile.mkstemp(suffix='.png')
        
        params = []
        
                
        
        try:
            
            width  = float(node.get('width', 'Not Found'))
            width *= float(transform['x']) 
            
            params.append("--export-width=%s" % width)
            
        except ValueError:
            params = params
            
        try:
            
            height  = float(node.get('height', 'Not found'))
            height *= float(transform['y'])
            
            params.append("--export-height=%s" % height)
            
        except ValueError:
            params = params
            
       
        mod_time        = os.path.getmtime(target_svg)
        rend_time       = float(node.get('data-file-last-modified', '0')) 
        
        if(self.float_equals(width, render_size[0]) and self.float_equals(height, render_size[1]) and rend_time >= mod_time ):
            #no need to render, so skip
            inkex.errormsg(_("Not Modified: ") + node.get("id", "No ID"))
            inkex.errormsg("%s >= %s = %s" % (rend_time, mod_time, str(rend_time >= mod_time)))
            return
        
        
        cmd = 'inkscape -z --export-png=%s %s "%s"' % (temp_file, ' '.join(params), target_svg)
        
        data = cmd  + "\n\n"
        data += command(cmd)
        
        #inkex.errormsg(data)
        
        node.set(inkex.addNS('absref','sodipodi'), temp_file);
        node.set(inkex.addNS('href','xlink'), temp_file);
        
        self.embeder.embedImage(node)
        
        node.set('data-render-size', "%sx%s" % (width, height));
        node.set('data-file-last-modified', str(time.time()))
        
        return
    
    
    
    def float_equals(self,a,b):
        
        try:
            
            if abs(float(a) - float(b)) < 0.000001:
                return True
            else:
                return False
        
        except ValueError:
            return False
    
    def render_embeds(self):
        
        if not os.path.exists(self.project.get_project_path()):
            inkex.errormsg(_("Project path is invalid!"))
        
        
        if(len(self.selected) > 0):
            
            # Render Selected Mode
            #
            nodes = []
            
            for id, node in self.selected.iteritems():
                
                if(node.get('data-embed', None) is not None):
                    nodes.append(node)
                
                nodes.extend(self.project.get_imports(node))
                
            
        else:
            #Render All Mode
            #
            nodes = self.project.get_imports()
                
        for node in nodes:
            
            self.render_node(node)
            #inkex.errormsg("node: %s\n" % node.get('data-embed', 'Not Found'))           
        
        self.project.draw_imports()
        return
    
    def setup_project(self):
        
        project = self.project.get_project_layer()
        
        if not os.path.exists(self.options.doc_path):
            inkex.errormsg(_("Project path is invalid."))
            return
        
        if project is None:
            self.project.create_project_layer()
        
        self.project.set_project_path(self.options.doc_path)
        
    
    def get_transform(self, node):
        
        if(node.tag == inkex.addNS('pattern', 'svg')):
            
            inkex.errormsg("Pattern Transform")
            transform = node.get('patternTransform', None)
        
        else:
            transform = node.get('transform', None)
        
        result = {'x' : 1, 'y': 1}
        
        if transform is not None:
                
                if "scale" in transform:
                    
                    transform = transform[6:-1]
                    transform = transform.split(',')
                    
                    result = {'x' : transform[0], 'y' : transform[1]}
                    
            
                if "matrix" in transform:
                    
                    transform = transform[7:-1]
                    transform = transform.split(',')
                    
                    result = {'x' : transform[0], 'y' : transform[3]}
         
        
        return result 
      
                    
        
    def make_rel_embed_path(self, path):
        
        start_point = self.project.get_project_path()
        
        if(len(start_point) > 0):
            
            path = os.path.relpath(path, start_point);
        
        return path
    
    def get_abs_embed_path(self, path):
    
        if(os.path.isabs(path)):
            return path
    
        # Check for changes in Project node and update local path.
        project_node = self.project.get_project_layer()
        
        
    
        start_point = self.project.get_project_path()
                        
        cwd = os.getcwd()
        
        if(len(start_point) > 0):
            
            os.chdir(start_point)
            path = os.path.abspath(path)
            os.chdir(cwd)
            return path    
        
        return None
    
    
    def edit_svg(self):
        
        if(len(self.selected) <= 0):
            inkex.errormsg(_('You have to select at least one linked SVG'))
            return False
        
        nodes = []
            
        for id, node in self.selected.iteritems():
            
            if(node.get('data-embed', None) is not None):
                nodes.append(node)
            
            nodes.extend(self.project.get_imports(node))
        
        
        # Collect already opened nodes, so svg should be opened twice
        opened = {}
                
        for node in nodes:
            
            rel_path = node.get('data-embed', None)
            abs_path = self.get_abs_embed_path(rel_path)
            
            if opened.get(abs_path, False) == False:
            
                opened[abs_path] = rel_path
                cmd = 'inkscape -g "%s"' % abs_path
                #inkex.errormsg(cmd)
                command(cmd)
                
                            
        # Render modified files
        for edited in nodes:
            
            nodes = self.document.xpath("//*[@data-embed='%s']" % edited.get('data-embed', ''))
            
            for node in nodes:
                self.render_node(node)
        
     
    def embed_svg(self):
         
        if(len(self.selected) <= 0):
            inkex.errormsg(_('You have to select at least one linked SVG'))
            return False
        
        nodes = []
            
        for id, node in self.selected.iteritems():
            
            if(node.get('data-embed', None) is not None):
                nodes.append(node)
            
            nodes.extend(self.project.get_imports(node))
         
         
        for node in nodes:
            
            rel_path = node.get('data-embed', None)
            abs_path = self.get_abs_embed_path(rel_path)
            
            if not os.path.exists(abs_path):
                inkex.errormsg(_('File Not Found: ') + abs_path)
                return
                                    
            doc = inkex.etree.parse(abs_path)
            
            temp_svg = tempfile.mktemp(".svg")
            
            doc.write(temp_svg)
            
            command('inkscape --vacuum-defs "%s"' % temp_svg)
            
            doc.parse(temp_svg)
            
            # Convert layers to groups
            #
            layers = doc.xpath("//*[@inkscape:groupmode='layer']", namespaces=inkex.NSS)
            
            for l in layers:
                #inkex.errormsg(l.get(inkex.addNS('label', 'inkscape'), 'No Label'))
                del(l[inkex.addNS('label', 'inkscape')])
            
            attribs = {}
            attribs[inkex.addNS('label','inkscape')] = doc.getroot().get(inkex.addNS('docname', 'sodipodi'), _('Imported SVG'))
                
            g = inkex.etree.subElement(self.current_layer, 'g', attribs)
            
            
        #doc = inkex.etree.parse()
         
        return True
        
        
    def effect(self):
       
       self.project = SvgLinkProject(self)
       self.project.get_project_layer()
       self.project.clear_linked_patterns(); 
       
       command = self.options.command
       
       if(command == "setup"):
            self.setup_project()
            return
       
       if(command == "Link"):
           self.create_link()
           return      
       
       if(command == "Render"):
            self.render_embeds()
            return
        
       if(command == "edit"):
            #self.edit_svg()
            self.embed_svg()
        

if __name__ == '__main__':
    e = Azijeon_SVG_Link()
    e.affect()



